/*****************************************************************************
Author:        zhangjw
Date:        2000/04/02

Class name:        TableBean

DBMS: Microsoft SQL Server v7.0

Description:
  This class is the base class of all the table beans, including basic open, close operations.

Methods:
  Constructor:
    TableBean(DbAdapter db)
    - Create a bean with transacation

    TableBean()
    - Create a bean without transacation, bean needs maintain database connection by itself

  Methods:
    private void init(DbAdapter db)
    - init function, called by constuctor

    pretected void makeConnection()
    throws TableBeanException
    - check if there is an valid database connection, if not, create one

    void close()
    throws TableBeanException
    - for non-transaction case, close database, called in subclass

================================================
    abstract         private        void        load()
    throws Exception;

    abstract        public        void        store()
    throws Exception;

    abstract        public        void refresh()
    throws Exception;

    abstract        protected        void create()
    throws Exception;

    abstract        protected        void        remove()
    throws Exception;

    abstract        protected        Enumeration findByKey()
    throws Exception;

    abstract        protected        Enumeration findBySql(String sqlWhere)
    throws Exception;
====== above abstract  methods should be override in subclass==================

*******************************************************************************/
package linuxbox.bean;

import java.sql.*;
import java.text.*;


import linuxbox.BoxStatic;
import linuxbox.exception.*;
import linuxbox.util.*;

import org.apache.log4j.Logger;


abstract public class TableBean {
    protected static Logger logger = Logger.getLogger(TableBean.class.getName());
    final static private String[] m_sNumTable = {
        "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", 
        "E", "F"
    };
    protected DbAdapter m_db = null;
    protected boolean m_bLoaded = false;
    private boolean m_bTransaction = false;
    private String m_sTableName = null;
    private String m_sUpdateSql = null;
    private boolean m_bFirstSet = true;

    public TableBean(DbAdapter db) {
        init(db);
    }

    public TableBean() {
        init(null);
    }

    protected void setTableName(String sName) {
        if (m_sTableName == null) {
            m_sTableName = sName;
        }
    }

    protected String getTableName() {
        return m_sTableName;
    }

    public String getSqlString() {
        return m_sUpdateSql;
    }

    protected void setString(String sName, String sValue) {
        if (sName != null) {
            if (m_bFirstSet) {
                m_bFirstSet = false;
                m_sUpdateSql = "";
            } else {
                m_sUpdateSql += ", ";
            }

            if (sValue == null) {
                m_sUpdateSql += (sName + "= null, ");
            } else {
                m_sUpdateSql += (sName + "= '" + sValue + "'");
            }
        }
    }

    protected void setInteger(String sName, int iValue) {
        if (sName != null) {
            if (m_bFirstSet) {
                m_bFirstSet = false;
                m_sUpdateSql = "";
            } else {
                m_sUpdateSql += ", ";
            }

            m_sUpdateSql += (sName + "=" + iValue);
        }
    }

    protected void setLong(String sName, long iValue) {
        if (sName != null) {
            if (m_bFirstSet) {
                m_bFirstSet = false;
                m_sUpdateSql = "";
            } else {
                m_sUpdateSql += ", ";
            }

            m_sUpdateSql += (sName + "=" + iValue);
        }
    }

    protected void setDate(String sName, java.sql.Date dtValue, 
                           java.sql.Time tmValue) {
        if (sName != null) {
            if (m_bFirstSet) {
                m_bFirstSet = false;
                m_sUpdateSql = "";
            } else {
                m_sUpdateSql += ", ";
            }

            if (dtValue == null) {
                m_sUpdateSql += (sName + "= null");
            } else {
                SimpleDateFormat df = new SimpleDateFormat(
                                              BoxStatic.POSTGRES_DATE_FORMAT);
                String dtStr = df.format(dtValue);
                df = new SimpleDateFormat(BoxStatic.POSTGRES_TIME_FORMAT);

                String tmStr = df.format(tmValue);
                dtStr = dtStr + " " + tmStr;

                m_sUpdateSql += (sName + "= '" + dtStr + "'");
            }

            logger.debug(m_sUpdateSql);
        }
    }

    protected void setTimestamp(String sName, Timestamp value) {
        if (sName != null) {
            if (m_bFirstSet) {
                m_bFirstSet = false;
                m_sUpdateSql = "";
            } else {
                m_sUpdateSql += ", ";
            }

            if (value == null) {
                m_sUpdateSql += (sName + "= null");
            } else {
                m_sUpdateSql += (sName + "= '" + value.toString() + "'");
            }

            logger.debug(m_sUpdateSql);
        }
    }

    protected void setRaw(String sName, byte[] abyValue) {
        if (sName != null) {
            if (m_bFirstSet) {
                m_bFirstSet = false;
                m_sUpdateSql = "";
            } else {
                m_sUpdateSql += ", ";
            }

            if (abyValue == null) {
                m_sUpdateSql += (sName + "= null");
            } else {
                int iLength = abyValue.length;
                String res = new String();

                for (int i = 0; i < iLength; i++) {
                    byte byCur;
                    byte byTemp;
                    byCur = abyValue[i];
                    byTemp = (byte)(byCur >> 4);
                    res += m_sNumTable[byTemp];

                    byTemp = (byte)(byCur & 15);
                    res += m_sNumTable[byTemp];
                }

                m_sUpdateSql += (sName + "= '" + res + "'");
            }

            logger.debug(m_sUpdateSql);
        }
    }

    protected void setText(String sName, byte[] byText) {
        if (sName != null) {
            if (m_bFirstSet) {
                m_bFirstSet = false;
                m_sUpdateSql = "";
            } else {
                m_sUpdateSql += ", ";
            }

            if (byText == null) {
                m_sUpdateSql += (sName + "= null");
            } else {
                StringBuffer sb = new StringBuffer();

                for (int i = 0; i < byText.length; i++) {
                    String str = Integer.toHexString(byText[i] & 0xff);

                    if (str.length() == 1) {
                        sb.append("0");
                    }

                    sb.append(str);
                }

                String tmp = "0x" + sb.toString();
                m_sUpdateSql += (sName + "= " + tmp);
            }

            logger.debug(m_sUpdateSql);
        }
    }

    protected void setNumber(String sName, String sValue) {
    }

    protected void updateTable(String sqlWhere) throws TableBeanException {
        if ((m_sTableName != null) && (!m_bFirstSet)) {
            m_sUpdateSql = "UPDATE " + m_sTableName + " set " + m_sUpdateSql + 
                           " where " + sqlWhere;

            try {
                makeConnection();
                logger.debug(m_sUpdateSql);
                m_db.executeUpdate(m_sUpdateSql);
                close();
                m_sUpdateSql = null;
                m_bFirstSet = true;
            } catch (DbBeanException e1) {
                close();
                throw new TableBeanException("Can't update: " + 
                                             e1.getMessage());
            }
        }
    }

    protected void makeConnection() throws TableBeanException {
        try {
            if (m_db == null) {
                //m_db = new DbAdapter(false);
                m_db = new DbAdapter(true);
            }
        } catch (DbBeanException e) {
            throw new TableBeanException("Can't make the connection: " + 
                                         e.getMessage());
        }
    }

    protected void init(DbAdapter db) {
        m_bTransaction = false;

        if (db != null) {
            m_db = db;
            m_bTransaction = true;
        }

        m_bLoaded = false;
    }

    protected void close() throws TableBeanException {
        if (m_bTransaction) {
            throw new TableBeanException("Can't close transcation connection.");
        }

        try {
            if (m_db != null) {
                m_db.close();
                m_db = null;
                logger.debug("Close the connection.\n");
            }
        } catch (DbBeanException dbe) {
            throw new TableBeanException("Can't close the connection: " + 
                                         dbe.getMessage());
        }
    }

    public int getCount() throws TableBeanException {
        int nCount = -1;

        if (m_sTableName != null) {
            String sCountSql = "select count(*) from " + m_sTableName;

            try {
                makeConnection();
                m_db.executeQuery(sCountSql);

                if (m_db.next()) {
                    nCount = m_db.getInt(1);
                }

                close();
            } catch (DbBeanException e1) {
                close();
                throw new TableBeanException("Can't get the Count: " + 
                                             e1.getMessage());
            }
        }

        return nCount;
    }

    public int getCount(String strWhere) throws TableBeanException {
        int nCount = -1;

        if (m_sTableName != null) {
            String sCountSql = "select count(*) from " + m_sTableName + " " + 
                               strWhere;

            try {
                makeConnection();
                m_db.executeQuery(sCountSql);

                if (m_db.next()) {
                    nCount = m_db.getInt(1);
                }

                close();
            } catch (DbBeanException e1) {
                close();
                throw new TableBeanException("Can't get the Count: " + 
                                             e1.getMessage());
            }
        }

        return nCount;
    }

    abstract protected void load() throws Exception;

    abstract public void store() throws Exception;

    abstract public void refresh() throws Exception;

    //	abstract protected void create() throws Exception;
    abstract protected void remove() throws Exception;

    //	abstract protected Object findByKey() throws Exception;
    //	abstract protected Enumeration findBySql(String sqlWhere) throws Exception;
    //	abstract protected Enumeration findBySql(String sqlWhere, int nMaxNum) throws Exception;
    //	abstract protected Enumeration findBySql(String sqlWhere, int nStartNum, int nRownum) throws Exception;
}